# -*- coding:utf-8 -*-

"""
@version: python2.7
@author: kun.wu
@license: Apache Licence 
@contact: kun.wu@bqjr.cn
@software: PyCharm
@file: GenPersonalInfo.py
@time: 2017/12/8 17:52
"""
import datetime
import random
from operator import mod
from AutoTestPlatForm import codearea_map


class GenRandomPersonalIDAddr(object):
    """
    生成个人身份相关信息：身份证；地址；
    """

    def __init__(self, Sex='Male', BirthYear=None, BirthMonth=None, BirthDay=None, ProvinceAddr=None, CityAddr=None):
        """
        初始化请求地址；公共地区编码与地址字典；
        """
        self.person_sex = Sex
        self.person_id = ''
        self.person_addr = ''
        self.person_birth = ''
        self.peron_provinceaddr = ProvinceAddr
        self.peron_cityaddr = CityAddr
        self.person_street = ''
        self.person_idaddr = {}
        self.__GetPersonalIdAddr(Sex, BirthYear, BirthMonth, BirthDay, ProvinceAddr, CityAddr)

    def __GetPersonalAddr(self, areacode):
        """
        生成随机地址,应有身份证号输出对应地址
        :return:
        """
        tmp_mainaddr = codearea_map.dict_provicecode[areacode[:2] + '0000']
        tmp_cityaddr = codearea_map.dict_provicecode[areacode[:4] + '00']
        tmp_county = codearea_map.dict_areacode[areacode]
        tmp_street = u'福田街道佰仟大楼3F'
        self.peron_provinceaddr = tmp_mainaddr
        self.peron_cityaddr = tmp_cityaddr
        self.person_street = tmp_county + tmp_street
        self.person_addr = tmp_mainaddr + tmp_cityaddr + tmp_county + tmp_street

    def __getareacodebyaddr(self, tmpaddr, type=0):
        """
        :param tmpaddr:
        :return:
        """
        if type == 0:
            tmp_header = codearea_map.reverse_dict_provicecode[tmpaddr][:2]
            for x in codearea_map.dict_areacode.keys():
                if tmp_header != x[:2]:
                    tmp_areacode = None
                else:
                    tmp_areacode = x
                    break
        else:
            tmp_header = codearea_map.reverse_dict_provicecode[tmpaddr][:4]
            for x in codearea_map.dict_areacode.keys():
                if tmp_header != x[:4]:
                    tmp_areacode = None
                else:
                    tmp_areacode = x
                    break
        return tmp_areacode

    def __GetPersonalAreaCode(self, MainAddr=None, CityAddr=None):
        """
        :param MainAddr:
        :param CityAddr:
        :return:
        """
        # 生成随机地址
        if not MainAddr and not CityAddr:
            # 获取随机地区编码及地址
            tmp_lendictareacode = len(codearea_map.dict_areacode.keys())
            tmp_areacode = codearea_map.dict_areacode.keys()[random.randint(0, tmp_lendictareacode - 1)]
        elif MainAddr and CityAddr:
            if CityAddr in codearea_map.reverse_dict_provicecode.keys():
                tmp_areacode = self.__getareacodebyaddr(CityAddr, 1)
            elif MainAddr in codearea_map.reverse_dict_provicecode.keys():
                tmp_areacode = self.__getareacodebyaddr(MainAddr)
            else:
                # 获取随机地区编码及地址
                tmp_lendictareacode = len(codearea_map.dict_areacode.keys())
                tmp_areacode = codearea_map.dict_areacode.keys()[random.randint(0, tmp_lendictareacode - 1)]
        elif MainAddr:
            if MainAddr in codearea_map.reverse_dict_provicecode.keys():
                tmp_areacode = self.__getareacodebyaddr(MainAddr)
            else:
                # 获取随机地区编码及地址
                tmp_lendictareacode = len(codearea_map.dict_areacode.keys())
                tmp_areacode = codearea_map.dict_areacode.keys()[random.randint(0, tmp_lendictareacode - 1)]
        elif CityAddr:
            if CityAddr in codearea_map.reverse_dict_provicecode.keys():
                tmp_areacode = self.__getareacodebyaddr(CityAddr, 1)
            else:
                # 获取随机地区编码及地址
                tmp_lendictareacode = len(codearea_map.dict_areacode.keys())
                tmp_areacode = codearea_map.dict_areacode.keys()[random.randint(0, tmp_lendictareacode - 1)]
        return tmp_areacode

    def __GetPersonalIdAddr(self, Sex='Male', BirthYear=None, BirthMonth=None, BirthDay=None, ProvinceAddr=None,
                            CityAddr=None):
        """

        :param Sex: str
        :param BirthYear: str
        :param BirthMonth: str
        :param ProvinceAddr: str
        :param CityAddr: str
        :return:
        """
        try:

            # 生成指定的地址
            tmp_areacode = self.__GetPersonalAreaCode(ProvinceAddr, CityAddr)
            self.__GetPersonalAddr(tmp_areacode)

            if not BirthYear:
                # 生成随机年份，年龄限制19-55岁
                tmp_current_year = datetime.datetime.now().year
                BirthYear = str(random.randint(tmp_current_year - 55, tmp_current_year - 18))
            else:
                BirthYear = str(BirthYear)

            if not BirthMonth:
                # 生成随机月份
                BirthMonth = str(random.randint(1, 12)).zfill(2)
            else:
                BirthMonth = str(BirthMonth).zfill(2)

            if not BirthDay:
                # 生成随机日1-28
                BirthDay = str(random.randint(1, 28)).zfill(2)
            else:
                BirthDay = str(BirthDay).zfill(2)

            self.person_birth = BirthYear + BirthMonth + BirthDay

            idNumber = ''
            # 顺序码
            for i in range(2):  # 产生前面的随机值
                n = random.randint(0, 9)  # 最后一个值可以包括
                idNumber += str(n)

            if Sex == 'Male':
                tmp_sex = 1
            else:
                tmp_sex = 0
                self.person_sex = 'Female'
            # 性别数字码
            sexId = random.randrange(tmp_sex, 10, step=2)
            idNumber = tmp_areacode + self.person_birth + idNumber + str(sexId)
            # 生成校验码
            aa = mod(reduce(lambda a, b: a + b, map(lambda (x, y): int(x) * int(y), zip(idNumber, codearea_map.Wi))),
                     11)
            idNumber += codearea_map.ModY[str(aa)]
            self.person_id = idNumber
            self.person_idAddr = {'id': self.person_id, 'addr': self.person_addr, 'province': self.peron_provinceaddr,
                                  'city': self.peron_cityaddr, 'street': self.person_street, 'sex': self.person_sex,
                                  'birth': self.person_birth}
        except BaseException, e:
            print u'获取身份证信息错误', e


class GenPersonalName(object):
    """
    生成随机的姓名
    """

    def __init__(self, lenfirstname=1, lastname=None, firstname=None):
        self.lastname = lastname
        self.firstname = firstname
        self.fullname = self.__GetFullName(lenfirstname, firstname, lastname)

    def __random_lastname(self, tmp_lastname=None):
        """
        :param tmp_lastname:
        :return:
        """
        try:
            if not tmp_lastname:
                tmp_lastname = codearea_map.last_names[random.randint(0, len(codearea_map.last_names) - 1)].decode(
                    'utf-8')
                raise u'生成lastname错误'
        finally:
            self.lastname = tmp_lastname
            return tmp_lastname

    def __random_firstname(self, size=1, tmp_firstname=None):
        """
        0x4E00:一unichr
        0x9FA5：详情查看unicode编码表http://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php
        :param size:
        :param tmp_firstname:
        :return:
        """
        try:
            if not tmp_firstname:
                tmp_times = int(size) if 0 < int(size) <= 3 else 3
                tmp_firstname = u''
                while tmp_times:
                    tmp_firstname += unichr(random.randint(0x4E00, 0x9FA5))
                    tmp_times -= 1
                raise u'生成firstname错误'
        finally:
            self.firstname = tmp_firstname
            return tmp_firstname

    def __GetFullName(self, lenfirstname=1, firstname=None, lastname=None):
        """
        :param lenfirstname:
        :param firstname:
        :param lastname:
        :return:
        """
        dict_returnname = {}
        try:
            lastname = self.__random_lastname(lastname)
            firstname = self.__random_firstname(lenfirstname, firstname)
            tmp_fullname = lastname + firstname
            dict_returnname['fullname'] = tmp_fullname
            dict_returnname['lastname'] = lastname
            dict_returnname['firstname'] = firstname
        except BaseException, e:
            print u'生成随机姓名错误', e
        finally:
            return dict_returnname


class GenPersonalBankInfo(object):
    """
    生成指定的银行卡号规则
    中国银行、中国建设银行、中国工商银行、交通银行、中国农业银行银联借记卡19位
    招商银行16位
    """

    def __init__(self, bankname=None, bankopen=None, lencardno='19'):
        self.bankname = bankname
        self.bankaccount = ''
        self.bankopen = bankopen
        self.bankinfo = self.__genbankinfo(bankname, bankopen, lencardno)

    def __genbankopen(self, bankopen=None):
        """
        生成开户行name & addr
        :param open:开户行名称
        :return:开户行编码
        """
        try:
            tmp_bank = u'支行'
            tmp_lendictprovince = len(codearea_map.dict_province.keys())  # 省编码字典长度
            tmp_bankcode = None  # 城市支行编码
            tmp_province = None  # 省名称
            tmp_city = None  # 市名称

            # 开户支行名称存在或不存在的情况处理
            if bankopen in codearea_map.dict_province.keys():
                tmp_province = bankopen
                tmp_provincecode = codearea_map.dict_province[tmp_province]
                tmp_lendictcity = len(codearea_map.dict_city[tmp_provincecode].keys())
                tmp_city = codearea_map.dict_city[tmp_provincecode].keys()[random.randint(0, tmp_lendictcity - 1)]
                tmp_bankcode = codearea_map.dict_city[tmp_provincecode][tmp_city]
            else:
                for x in codearea_map.dict_city.keys():
                    if tmp_bankcode:
                        break
                    else:
                        for y in codearea_map.dict_city[x].keys():
                            if bankopen == y:
                                tmp_bankcode = codearea_map.dict_city[x][y]
                                tmp_city = y
                                break

                if tmp_bankcode:
                    tmp_province = \
                    [key for key, value in codearea_map.dict_province.items() if tmp_bankcode[:2] == value][0]
                else:
                    print u'传入开户支行不存在！随机生成开户支行中......'
                    tmp_province = codearea_map.dict_province.keys()[random.randint(0, tmp_lendictprovince - 1)]
                    tmp_provincecode = codearea_map.dict_province[tmp_province]
                    tmp_lendictcity = len(codearea_map.dict_city[tmp_provincecode].keys())
                    tmp_city = codearea_map.dict_city[tmp_provincecode].keys()[random.randint(0, tmp_lendictcity - 1)]
                    tmp_bankcode = codearea_map.dict_city[tmp_provincecode][tmp_city]
            self.bankopen = tmp_province + tmp_city + tmp_bank
        except BaseException, e:
            print u'生成开户行地址错误', e
        finally:
            return tmp_bankcode

    def __genbankaccount(self, bankcode, bankname=None, lencardno='19'):
        """
        生成银行卡号：16或19位
        :param bankname: 银行名
        :param lencardno: 卡号长度
        :return: 返回开户账号
        """
        try:
            tmp_bankaccount = None
            tmp_cardbin = None

            # 设置默认生成的卡号长度位19位
            if lencardno != '19' and lencardno != '16':
                print u'暂不支持卡号长度为16或19位以外生成！'
                lencardno = '19'

            # 开户行名称存在或不存在的情况处理
            if bankname in codearea_map.debitcardbin[lencardno].keys():
                self.bankname = bankname
            else:
                tmp_lenbankname = len(codearea_map.debitcardbin[lencardno].keys())
                self.bankname = codearea_map.debitcardbin[lencardno].keys()[random.randint(0, tmp_lenbankname - 1)]
            tmp_lencardbin = len(codearea_map.debitcardbin[lencardno][self.bankname])
            tmp_cardbin = codearea_map.debitcardbin[lencardno][self.bankname][random.randint(0, tmp_lencardbin - 1)]

            # 卡种类生成码占位1
            tmp_cardtype = str(random.randint(0, 9))

            # 顺序码
            tmp_cardseq = ''
            for i in range(int(lencardno) - 12):  # 产生前面的随机值19-7位，16-4位
                n = random.randint(0, 9)  # 最后一个值可以包括
                tmp_cardseq += str(n)

            # 校验位LUNH算法
            tmp_fontaccount = tmp_cardbin + bankcode + tmp_cardtype + tmp_cardseq
            total = 0
            for item in tmp_fontaccount[-1::-2]:
                item = int(item)
                item <<= 1
                if item > 9:
                    item -= 9
                total += item
            for item in tmp_fontaccount[-2::-2]:
                total += int(item)
            tmp_verify = (10 - mod(total, 10)) % 10
            tmp_bankaccount = tmp_fontaccount + str(tmp_verify)

        except BaseException, e:
            print u'生成银行卡号错误', e
        finally:
            return tmp_bankaccount

    def __genbankinfo(self, bankname=None, bankopen=None, lencardno='19'):
        """
        :param bankname:
        :param bankopen:
        :param lencardno:
        :return:
        """
        dict_returncardinfo = {}
        try:
            tmp_bankcode = self.__genbankopen(bankopen)
            tmp_bankaccount = self.__genbankaccount(tmp_bankcode, bankname)
            dict_returncardinfo['bankopen'] = self.bankopen
            dict_returncardinfo['bankaccount'] = tmp_bankaccount
            dict_returncardinfo['bankname'] = self.bankname
        except BaseException, e:
            print u'生成随机姓名错误', e
        finally:
            return dict_returncardinfo
